/**
 *
 */
package com.example.javafx.bilibilidownload.util;

import com.example.javafx.bilibilidownload.constant.VideoConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.example.javafx.bilibilidownload.util.OpetateFileUtil.checkOrigin;
import static com.example.javafx.bilibilidownload.util.OpetateFileUtil.checkOriginAndTarget;
import static com.example.javafx.bilibilidownload.util.OpetateFileUtil.checkTarget;


public final class VideoCommandUtils {

    private static final Logger log = LogManager.getLogger(VideoCommandUtils.class);


    private VideoCommandUtils() {
        //
    }

    /**
     * 检测环境
     */
    public static List<String> mergeVideoAudio(String videoAbsPath, String audioAbsPath, String realAbsPath, boolean useGpu) {
        checkTarget(realAbsPath);
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
        cmd.add("-y");
        cmd.add("-i");
        cmd.add(videoAbsPath);
        cmd.add("-i");
        cmd.add(audioAbsPath);
        cmd.add("-c:v");
        cmd.add("copy");
        cmd.add("-c:a");
        cmd.add("copy");
        cmd.add(realAbsPath);
        return cmd;
    }

    /**
     * 检测环境
     */
    public static List<String> checkFfmpegCommands() {
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
        cmd.add("--version");
        return cmd;
    }


    /**
     * 获取视频基本信息命令
     *
     * @param videoAbsPath
     * @return
     */
    public static List<String> getVideoInfoCommands(String videoAbsPath) {
        checkOrigin(videoAbsPath);
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
        // 指定输入文件名
        cmd.add("-i");
        cmd.add(videoAbsPath);
        return cmd;
    }

    /**
     * 视频文件分离出单独的音轨文件
     *
     * @param videoAbsPath
     * @param audioAbsPath
     * @return
     */
    public static List<String> getAudioFromVideoCommands(String videoAbsPath, String audioAbsPath) {
        checkOriginAndTarget(videoAbsPath, audioAbsPath);
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
        cmd.add("-i");
        cmd.add(videoAbsPath);
        cmd.add("-f");
        cmd.add("mp3");
        cmd.add("-vn");// no video，去除视频信息
        cmd.add("-y");
        cmd.add(audioAbsPath);
        log.info(Arrays.toString(cmd.toArray()));
        return cmd;
    }

    /**
     * 根据m3u8下载视频文件
     *
     * @param m3u8Path
     * @param videoAbsPath
     * @return
     */
    public static List<String> downloadVideoCommands(String m3u8Path, String videoAbsPath) {
        checkTarget(videoAbsPath);
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
//        cmd.add("-rw_timeout ");
//        cmd.add(VideoConstant.DEFAULT_TIMEOUT_TIME);
        cmd.add("-i");
        cmd.add(m3u8Path);
        cmd.add(videoAbsPath);
//        log.info(Arrays.toString(cmd.toArray()));
        return cmd;
    }

    /**
     * @Description:传入字符串的命令
     * @Param: [command]
     * @return: java.util.List<java.lang.String>
     * @Author: Mr.zengbang
     * @Date: 2020/12/13
     */
    public static List<String> downloadVideoCommands(String command) {
        List<String> cmd = new ArrayList<String>(Arrays.asList(command.split(" ")));
        return cmd;
    }

    public static List<String> convertTsToMp4(String originFilePath, String targetFilePath) {

        checkOriginAndTarget(originFilePath, targetFilePath);
        List<String> cmd = new ArrayList<String>();
        cmd.add("ffmpeg");
        cmd.add("-y");
        cmd.add("-i");
        cmd.add(originFilePath);
        cmd.add(targetFilePath);
        log.info(Arrays.toString(cmd.toArray()));
        return cmd;
    }

    /**
     * 从视频获取指定时间点的静态缩略图
     *
     * @param videoAbsPath
     * @param pngAbsPath
     * @param startTime
     * @return
     */
    public static List<String> getThumbnailPngFromVideoCommands(String videoAbsPath, String pngAbsPath,
                                                                String startTime, String pngResolve) {
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
        cmd.add("-i");
        cmd.add(videoAbsPath);
        /**
         * 指定开始时间
         */
        cmd.add("-ss");
        cmd.add(startTime);
        /**
         * 指定静态图分辨率(videoResolve转码视频源分辨率)
         */
        cmd.add("-s");
        cmd.add(pngResolve);
        cmd.add("-vframes");
        cmd.add("1");
        cmd.add("-y");
        cmd.add(pngAbsPath);
        log.info(Arrays.toString(cmd.toArray()));
        return cmd;
    }

    /**
     * 从视频获取指定时间点的持续时间段动态缩略图
     *
     * @param videoAbsPath
     * @param gifAbsPath
     * @param startTime
     * @param durationTime
     * @return
     */
    public static List<String> getThumbnailGifFromVideoCommands(String videoAbsPath, String gifAbsPath,
                                                                String startTime, String durationTime, String gifResolve) {
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
        /**
         * 从指定的时间(s)开始
         */
        cmd.add("-ss");
        cmd.add(startTime);
        /**
         * 持续时间，如-t 4表示持续4s
         */
        cmd.add("-t");
        cmd.add(durationTime);
        cmd.add("-i");
        cmd.add(videoAbsPath);
        /**
         * 设置分辨率
         */

        cmd.add("-s");
        cmd.add(gifResolve);

        /**
         * 表示帧率，网上下载的视频帧率通常为 24
         */
        cmd.add("-r");
        cmd.add("24");
        cmd.add("-y");
        cmd.add(gifAbsPath);
        log.info(Arrays.toString(cmd.toArray()).replace(",", ""));
        return cmd;
    }

    /**
     * 视频转h264格式中间mp4文件
     *
     * @param videoAbsPath
     * @param mp4AbsPath
     * @param videoResolve
     * @param crf
     * @return
     */
    public static List<String> getTranscodeVideoToH264Mp4Commands(String[] waterMarkParam, String videoAbsPath,
                                                                  String mp4AbsPath, String videoResolve, String crf, String fontFilePath) {
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
        // 指定输入文件名
        cmd.add("-i");
        cmd.add(videoAbsPath);
       /* // 设置码率
        cmd.add("-b:v");
        cmd.add(VideoResolutionEnum.getVideoResolutionEnumByCode(videoResolve).getBitrate());
        cmd.add("-bufsize");
        cmd.add(VideoResolutionEnum.getVideoResolutionEnumByCode(videoResolve).getBitrate());
        cmd.add("-maxrate");
        cmd.add(VideoResolutionEnum.getVideoResolutionEnumByCode(videoResolve).getBitrate());*/
        /**
         * 指定分辨率 (360p 480×360 480p 720x480 720p 1280x720 1080p 1920x1080)
         */
        cmd.add("-s");
        cmd.add(videoResolve);
        cmd.add("-vcodec");
        cmd.add("libx264");
        cmd.add("-strict");
        cmd.add("-2");
        /**
         * 覆盖输出文件，即如果1.***文件已经存在的话，不经提示就覆盖掉了
         */
        cmd.add("-y");
        cmd.add("-hide_banner");
        // 设置视频质量
       /* cmd.add("-crf");
        cmd.add(StringUtils.isEmpty(crf)
                ? VideoResolutionEnum.getVideoResolutionEnumByCode(videoResolve).getCrf().toString()
                : crf);*/
        // 在视频头部增加视频信息
        cmd.add("-movflags");
        cmd.add("faststart");
        if (waterMarkParam[0].equals("true")) {
            cmd.add("-vf");
            String waterMarkStringParam = String.format(
                    "drawtext=fontfile=%s:text=%s:x=%s:y=%s:fontsize=%s:fontcolor=white:shadowy=2", fontFilePath,
                    waterMarkParam[1], waterMarkParam[2], waterMarkParam[3], waterMarkParam[4]);
            cmd.add(waterMarkStringParam);
            /*
             * cmd.add("\"drawtext="); cmd.add("fontfile=" + SysConf.fontTtfPath);
             * cmd.add(":text=" + waterMarkParam[1]); cmd.add(":" + waterMarkParam[2]);
             * cmd.add(":fontsize=80:fontcolor=white:shadowy=2\"");
             */
        }
        cmd.add(mp4AbsPath);
        log.info(Arrays.toString(cmd.toArray()));
        return cmd;
    }

    /**
     * 从h264格式中间mp4文件中获取faststart
     *
     * @param sourceVideoAbsPath
     * @param targetVideoAbsPath
     * @return
     */
    @Deprecated
    public static List<String> getFastStartFromH264Mp4VideoCommands(String sourceVideoAbsPath,
                                                                    String targetVideoAbsPath) {
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.QT_FASTSTART);
        cmd.add(sourceVideoAbsPath);
        cmd.add(targetVideoAbsPath);
        return cmd;
    }


    /**
     * 视频切割成ts文件,并加密
     *
     * @param videoAbsPath
     * @param subM3u8AbsPath
     * @param tsNAbsPath
     * @param videoResolve
     * @return
     */
    public static List<String> getVideoCutToTsCommandsByHlsEncode(String keyInfoFileAbsPath, String videoAbsPath, String subM3u8AbsPath, String tsNAbsPath,
                                                                  String videoResolve) {
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
        // 指定输入文件名
        cmd.add("-y");
        cmd.add("-i");
        cmd.add(videoAbsPath);
        // 在视频头部增加视频信息
        cmd.add("-movflags");
        cmd.add("faststart");
        cmd.add("-f");
        cmd.add("hls");
      /*  cmd.add("-hls_time");
        cmd.add(VideoResolutionEnum.getVideoResolutionEnumByCode(videoResolve).getSegmentTime().toString());*/
        cmd.add("-hls_list_size");
        cmd.add("0");
        cmd.add("-hls_key_info_file");
        cmd.add(keyInfoFileAbsPath);
        cmd.add("-hls_playlist_type");
        cmd.add("vod");
        cmd.add("-hls_segment_filename");
        cmd.add(tsNAbsPath);
        cmd.add(subM3u8AbsPath);
        return cmd;
    }

    /**
     * 视频切割成ts文件
     *
     * @param videoAbsPath
     * @param subM3u8AbsPath
     * @param tsNAbsPath
     * @param videoResolve
     * @return
     */
    public static List<String> getVideoCutToTsCommands(String videoAbsPath, String subM3u8AbsPath, String tsNAbsPath,
                                                       String videoResolve) {
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
        // 指定输入文件名
        cmd.add("-y");
        cmd.add("-i");
        cmd.add(videoAbsPath);
        cmd.add("-f");
        cmd.add("segment");
       /* cmd.add("-segment_time");
        // cmd.add("-hls_time");
        cmd.add(VideoResolutionEnum.getVideoResolutionEnumByCode(videoResolve).getSegmentTime().toString());*/
        // cmd.add("-hls_key_info_file");
        // cmd.add(encryFilePath);
        // cmd.add("-hls_playlist_type vod -hls_segment_filename");
        cmd.add("-segment_format");
        cmd.add("mpegts");
        cmd.add("-segment_list");
        cmd.add(subM3u8AbsPath);
        cmd.add("-c");
        cmd.add("copy");
        cmd.add("-bsf:v");
        cmd.add("h264_mp4toannexb");
        cmd.add("-map");
        cmd.add("0");
        // 在视频头部增加视频信息
        cmd.add("-movflags");
        cmd.add("faststart");
        cmd.add(tsNAbsPath);
        return cmd;
    }

    /**
     * 视频生成缩略图供vtt使用
     *
     * @param videoAbsPath
     * @param thumbsNAbsPath
     * @param timeInterval   时间间隔
     * @param vttWidth       时间间隔
     * @return
     */
    public static List<String> getVideoGenerateThumbnailsForVttCommands(String videoAbsPath, String thumbsNAbsPath, int timeInterval, String vttWidth) {
        List<String> cmd = new ArrayList<String>();
        cmd.add(VideoConstant.getFFMPEGPath());
        // 指定输入文件名
        cmd.add("-y");
        cmd.add("-i");
        cmd.add(videoAbsPath);
        cmd.add("-an");
        cmd.add("-sn");
        cmd.add("-vsync");
        cmd.add("0");
        cmd.add("-q:v");
        cmd.add("5");
        cmd.add("-threads");
        cmd.add("1");
        cmd.add("-vf");
//        String videoFilter = String.format(
//                "scale=%s:-1,select=(gte(t\\,%d))*(isnan(prev_selected_t)+gte(t-prev_selected_t\\,%d))",
//                vttWidth, timeInterval,
//                timeInterval);
        String videoFilter = String.format(
                "scale=%s:%s,select=(gte(t\\,%d))*(isnan(prev_selected_t)+gte(t-prev_selected_t\\,%d))",
                120, 50, timeInterval,
                timeInterval);
        cmd.add(videoFilter);
        cmd.add(thumbsNAbsPath);
        return cmd;
    }


}
